package com.vhall.component.service.rbac.impl;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.vhall.component.dao.rbac.RbacGroupAccessMapper;
import com.vhall.component.entity.rbac.GroupAccessEntity;
import com.vhall.component.entity.rbac.vo.GroupAddAccessReqVO;
import com.vhall.component.entity.rbac.vo.GroupDeleteAccessReqVO;
import com.vhall.component.entity.rbac.vo.GroupVO;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.service.rbac.RbacAccessService;
import com.vhall.component.service.rbac.RbacGroupAccessService;
import com.vhall.component.service.rbac.RbacGroupService;
import com.vhall.component.service.rbac.constant.AccessConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author dalong
 * @date 2021-05-10 18:13
 */
@Service
public class RbacGroupAccessServiceImpl implements RbacGroupAccessService {

    @Autowired
    private RbacGroupAccessMapper groupAccessMapper;

    @Autowired
    private RbacGroupService groupService;

    @Autowired
    private RbacAccessService accessService;


    @Override
    public List<GroupAccessEntity> getListByGroupIdAppId(Integer groupId, String appId) {
        List<GroupAccessEntity> groupAccessEntities = new ArrayList<>();
        // 查询分组信息
        GroupVO groupEntity = groupService.getInfoByGroupIdStatus(groupId, AccessConstant.NORMAL_STATUS);
        if (groupEntity == null) {
            return groupAccessEntities;
        }
        // 查询分组权限列表
        LambdaQueryWrapper<GroupAccessEntity> where = Wrappers.lambdaQuery();
        where.eq(GroupAccessEntity::getStatus, AccessConstant.NORMAL_STATUS)
                .eq(GroupAccessEntity::getGroupId, groupEntity.getId())
                .isNull(GroupAccessEntity::getDeletedAt);
        groupAccessEntities = groupAccessMapper.selectList(where);
        return groupAccessEntities;
    }

    @Override
    public boolean addGroupAccess(GroupAddAccessReqVO reqVO) {
        List<Integer> idList;
        try {
            JSONArray accessIds = JSONObject.parseArray(reqVO.getAccessId());
            idList = accessIds.toJavaList(Integer.class);
        } catch (Exception e) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
        }
        boolean checkResult = accessService.checkAccessId(idList);
        if (!checkResult) {
            throw new BusinessException(BizErrorCode.AUTH_ACCESS_EMPTY);
        }
        // create
        for (Integer accessId : idList) {
            GroupAccessEntity groupAccessEntity = getInfoByGroupIdAccessId(reqVO.getGroupId(), accessId);
            if (groupAccessEntity == null) {
                groupAccessEntity = new GroupAccessEntity();
                groupAccessEntity.setAccessId(accessId);
                groupAccessEntity.setGroupId(reqVO.getGroupId());
                groupAccessMapper.insert(groupAccessEntity);
            } else {
                if (AccessConstant.DEL_STATUS.equals(groupAccessEntity.getStatus())) {
                    // update
                    groupAccessEntity.setUpdatedAt(LocalDateTime.now());
                    groupAccessEntity.setStatus(AccessConstant.NORMAL_STATUS);
                    groupAccessMapper.updateById(groupAccessEntity);
                }
            }
        }
        return true;
    }

    @Override
    public boolean deleteGroupAccess(GroupDeleteAccessReqVO reqVO) {
        List<String> accessIdList;
        try {
            accessIdList = JSONObject.parseArray(reqVO.getAccessId(), String.class);
        } catch (Exception e) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
        }
        LambdaUpdateWrapper<GroupAccessEntity> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(GroupAccessEntity::getGroupId, reqVO.getGroupId())
                .in(GroupAccessEntity::getAccessId, accessIdList)
                .set(GroupAccessEntity::getStatus, AccessConstant.DEL_STATUS)
                .set(GroupAccessEntity::getDeletedAt, LocalDateTime.now());
        groupAccessMapper.update(null, updateWrapper);
        return true;
    }

    @Override
    public GroupAccessEntity getInfoByGroupIdAccessId(Integer groupId, Integer accessId) {
        LambdaQueryWrapper<GroupAccessEntity> where = Wrappers.lambdaQuery();
        where.eq(GroupAccessEntity::getGroupId, groupId)
                .eq(GroupAccessEntity::getAccessId, accessId)
                .isNull(GroupAccessEntity::getDeletedAt)
                .last("LIMIT 1");
        return groupAccessMapper.selectOne(where);
    }

    @Override
    public GroupAccessEntity getInfoByGroupStatus(Integer groupId, Integer status) {
        LambdaQueryWrapper<GroupAccessEntity> where = Wrappers.lambdaQuery();
        where.eq(GroupAccessEntity::getGroupId, groupId)
                .eq(GroupAccessEntity::getStatus, status)
                .isNull(GroupAccessEntity::getDeletedAt)
                .last("LIMIT 1");
        return groupAccessMapper.selectOne(where);
    }
}
